﻿// (c) Comkarl Calipso
// By Matías Fidemraizer (http://www.matiasfidemraizer.com)
// -------------------------------------------------
// http://calipso.codeplex.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

(function ($) {
    "use strict";

    $namespace.using("comkarl.web", "comkarl.web.ui.controls", function (web, controls) {
        /// <summary>Represents the base class for all client-side ScriptControls</summary>
        controls.declareClass("Control", {
            ctor: function (args) {
                this._.id = null;
                this._.name = null;
                this._.elementCssClass = null;
                this._.element = null;
                this._.parentElementSelector = null;
                this._.applicationPath = null;
                this._.validationRelations = null;
            },
            members: {
                get name() {
                    return this._.name;
                },

                set name(value) {
                    this._.name = value;
                },

                get validationRelations() {
                    return this._.validationRelations;
                },

                set validationRelations(value) {
                    this._.validationRelations = value;
                },

                get applicationPath() {
                    return this._.applicationPath;
                },

                set applicationPath(value) {
                    this._.applicationPath = value;
                },

                get parentElementSelector() {
                    return this._.parentElementSelector;
                },

                set parentElementSelector(value) {
                    this._.parentElementSelector = value;
                },

                /// <summary>Gets control's identifier.</summary>
                get id() {
                    return this._.id;
                },

                /// <summary>Sets control identifier. This can be set once per page life-cycle </summary>
                set id(value) {
                    if (this._.id == undefined || this._.id == null) {
                        this._.id = value;
                    }
                    else {
                        throw Error("Control identifier can be set once");
                    }
                },

                /// <summary>Gets the HTML element which this control represents.</summary>
                get element() {
                    if (this._.element == null) {
                        this.element = $("." + this.elementCssClass.trim().replace(" ", "."))[0];
                    }

                    return this._.element;
                },

                /// <summary>Sets the HTML element which this control represents.</summary>
                set element(value) {
                    this._.element = value;
                },


                /// <summary>Gets the CSS class of current control container HTML element.</summary>
                get elementCssClass() {
                    return this._.elementCssClass;
                },


                /// <summary>Sets the CSS class of current control container HTML element.</summary>
                set elementCssClass(value) {
                    this._.elementCssClass = value;
                },

                getGlobalResources: function (name) {
                    // Next if statements are there in order to prevent errors. Just imagine the situation
                    // where resources were not found. Instead of getting an error, this way you should get
                    // a undefined for the label, instead of the entire resource object.
                    if (!web.resources) {
                        web.resources = {};
                    }

                    if (!web.resources[name]) {
                        web.resources[name] = {};
                    }

                    return web.resources[name];
                },

                /// <summary>Gets the localization resources as object</summary>
                get resources() {
                    return this.getGlobalResources(this.name);
                },

                /// <summary>Disables all interaction with current control.</summary>
                set disabled(value) {
                    $("." + this.elementCssClass + " input, ." + this.elementCssClass + " textarea" + " ." + this.elementCssClass + " button").attr("disabled", value);
                },

                /// <summary>In inherited classes, initializes related resources, events, objects and others for current control</summary>
                initialize: function () {
                    $(this.element).addClass("control-container");
                },

                /// <summary>In inherited classes, creates child controls, and renders them.</summary>
                render: function () {
                },

                validateRelations: function (data) {
                    var that = this;

                    var renderErrors = function () {
                        $(".brokenfield-info").remove();
                        $("." + that.elementCssClass + " .brokenfield").removeClass("brokenfield");

                        if (data.Errors && that.validationRelations) {
                            var tempBrokenField;
                            var tempError;
                            var tempAffectedResourceText;

                            var errors = data.Errors;

                            if (!errors) {
                                errors = data.errors;
                            }

                            if (errors) {
                                var tempAffectedResources;

                                for (var errorIndex = 0; errorIndex < errors.length; errorIndex++) {
                                    tempError = errors[errorIndex];

                                    tempAffectedResources = tempError.AffectedResources;

                                    if (typeof tempAffectedResources != "undefined") {
                                        for (var fieldName in tempAffectedResources) {
                                            tempAffectedResourceText = tempAffectedResources[fieldName];
                                            fieldName = fieldName.substring(fieldName.indexOf(".") + 1);
                                            tempBrokenField = $(that.validationRelations[fieldName]);

                                            that.derived.renderValidatedResource(tempBrokenField, tempAffectedResourceText);

                                            if (!tempBrokenField.hasClass("brokenfield")) {
                                                tempBrokenField.addClass("brokenfield");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    };

                    var errorInfos = $("." + this.elementCssClass + " .brokenfield-info");

                    if (errorInfos.length > 0) {
                        errorInfos.fadeOut(renderErrors);
                    }
                    else {
                        renderErrors();
                    }
                },

                renderValidatedResource: function (brokenField, validationText) {
                    var pnlBrokenFieldInfo = $("<div />");
                    pnlBrokenFieldInfo.addClass("brokenfield-info");
                    pnlBrokenFieldInfo.text(validationText);
                    pnlBrokenFieldInfo.hide();
                    brokenField.after(pnlBrokenFieldInfo);
                    pnlBrokenFieldInfo.fadeIn();
                },

                resolvePath: function (relativePath) {
                    return (this.applicationPath + "/" + relativePath).replace("//", "/");
                },

                onProxyCall: function () {
                },

                onProxyCallEnd: function (response) {
                },

                addProxyPostPromises: function (promise) {
                },

                asyncCallback: function (data, textStatus, response, innerCallback) {
                    var entity = $.parseJSON(response.responseText);
                    this.validateRelations(entity);

                    if (innerCallback) {
                        innerCallback(response, entity);
                    }

                    this.derived.onProxyCallEnd(response);
                },

                postProxy: function (operationName, args, callback) {
                    var that = this;

                    this.derived.onProxyCall();

                    var promise = $.post(
                        this.resolvePath("proxy/" + operationName),
                        { proxyArgs: JSON.stringify(args) }
                    ).done(function (data, textStatus, response) {
                        that.asyncCallback(data, textStatus, response, callback);
                    }).fail(function (response, textStatus, errorThrown) {
                        that.asyncCallback(null, textStatus + "(HTTP error: " + errorThrown + ")", null, callback);
                    });

                    this.derived.addProxyPostPromises(promise);

                    return promise;
                }
            }
        });
    });
})(jQuery);

var $calipso$control = $global.comkarl.web.ui.controls.Control;